{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "import pickle\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from imblearn.over_sampling import SMOTE\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.metrics import classification_report, confusion_matrix, accuracy_score\n",
    "from sklearn.pipeline import Pipeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# list of .csv files in the directory\n",
    "incart_csv = 'INCART 2-lead Arrhythmia Database' # this is the most relevant at the current time of writing this\n",
    "arr_csv = 'MIT-BIH Arrhythmia Database'\n",
    "supra_csv = 'MIT-BIH Supraventricular Arrhythmia Database'\n",
    "scdh_csv = 'Sudden Cardiac Death Holter Database'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "csv_path = os.path.join('..',\n",
    "                        'raw_data', # root directory of the dataset folder\n",
    "                        f'{incart_csv}.csv' # which csv are we looking at?\n",
    "                        )\n",
    "df = pd.read_csv(csv_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "../raw_data/INCART 2-lead Arrhythmia Database.csv\n"
     ]
    }
   ],
   "source": [
    "print(csv_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The \"INCART 2-lead Arrhythmia Database\" has 175729 rows and 34 columns.\n"
     ]
    }
   ],
   "source": [
    "rows = df.shape[0]\n",
    "cols = df.shape[1]\n",
    "print(f'The \"{incart_csv}\" has {rows} rows and {cols} columns.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>record</th>\n",
       "      <th>type</th>\n",
       "      <th>0_pre-RR</th>\n",
       "      <th>0_post-RR</th>\n",
       "      <th>0_pPeak</th>\n",
       "      <th>0_tPeak</th>\n",
       "      <th>0_rPeak</th>\n",
       "      <th>0_sPeak</th>\n",
       "      <th>0_qPeak</th>\n",
       "      <th>0_qrs_interval</th>\n",
       "      <th>...</th>\n",
       "      <th>1_qPeak</th>\n",
       "      <th>1_qrs_interval</th>\n",
       "      <th>1_pq_interval</th>\n",
       "      <th>1_qt_interval</th>\n",
       "      <th>1_st_interval</th>\n",
       "      <th>1_qrs_morph0</th>\n",
       "      <th>1_qrs_morph1</th>\n",
       "      <th>1_qrs_morph2</th>\n",
       "      <th>1_qrs_morph3</th>\n",
       "      <th>1_qrs_morph4</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>I01</td>\n",
       "      <td>N</td>\n",
       "      <td>163</td>\n",
       "      <td>165</td>\n",
       "      <td>0.069610</td>\n",
       "      <td>-0.083281</td>\n",
       "      <td>0.614133</td>\n",
       "      <td>-0.392761</td>\n",
       "      <td>0.047159</td>\n",
       "      <td>15</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.023370</td>\n",
       "      <td>14</td>\n",
       "      <td>3</td>\n",
       "      <td>23</td>\n",
       "      <td>6</td>\n",
       "      <td>-0.023370</td>\n",
       "      <td>-0.011650</td>\n",
       "      <td>0.082608</td>\n",
       "      <td>0.101373</td>\n",
       "      <td>-0.183387</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>I01</td>\n",
       "      <td>N</td>\n",
       "      <td>165</td>\n",
       "      <td>166</td>\n",
       "      <td>-0.097030</td>\n",
       "      <td>0.597254</td>\n",
       "      <td>-0.078704</td>\n",
       "      <td>-0.078704</td>\n",
       "      <td>-0.137781</td>\n",
       "      <td>3</td>\n",
       "      <td>...</td>\n",
       "      <td>0.081637</td>\n",
       "      <td>15</td>\n",
       "      <td>5</td>\n",
       "      <td>27</td>\n",
       "      <td>7</td>\n",
       "      <td>0.081637</td>\n",
       "      <td>0.102992</td>\n",
       "      <td>0.191225</td>\n",
       "      <td>0.217544</td>\n",
       "      <td>-0.068248</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>I01</td>\n",
       "      <td>N</td>\n",
       "      <td>166</td>\n",
       "      <td>102</td>\n",
       "      <td>0.109399</td>\n",
       "      <td>0.680528</td>\n",
       "      <td>-0.010649</td>\n",
       "      <td>-0.010649</td>\n",
       "      <td>-0.720620</td>\n",
       "      <td>6</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.148539</td>\n",
       "      <td>33</td>\n",
       "      <td>13</td>\n",
       "      <td>52</td>\n",
       "      <td>6</td>\n",
       "      <td>-0.148539</td>\n",
       "      <td>-0.060620</td>\n",
       "      <td>0.081080</td>\n",
       "      <td>0.204400</td>\n",
       "      <td>0.335172</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>I01</td>\n",
       "      <td>VEB</td>\n",
       "      <td>102</td>\n",
       "      <td>231</td>\n",
       "      <td>0.176376</td>\n",
       "      <td>0.256431</td>\n",
       "      <td>-0.101098</td>\n",
       "      <td>-0.707525</td>\n",
       "      <td>-0.101098</td>\n",
       "      <td>4</td>\n",
       "      <td>...</td>\n",
       "      <td>0.046898</td>\n",
       "      <td>21</td>\n",
       "      <td>9</td>\n",
       "      <td>34</td>\n",
       "      <td>4</td>\n",
       "      <td>0.046898</td>\n",
       "      <td>0.083728</td>\n",
       "      <td>0.279512</td>\n",
       "      <td>0.526785</td>\n",
       "      <td>0.450969</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>I01</td>\n",
       "      <td>N</td>\n",
       "      <td>231</td>\n",
       "      <td>165</td>\n",
       "      <td>0.585577</td>\n",
       "      <td>0.607461</td>\n",
       "      <td>-0.083499</td>\n",
       "      <td>-0.083499</td>\n",
       "      <td>-0.167858</td>\n",
       "      <td>3</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.112552</td>\n",
       "      <td>32</td>\n",
       "      <td>5</td>\n",
       "      <td>43</td>\n",
       "      <td>6</td>\n",
       "      <td>-0.112552</td>\n",
       "      <td>0.012989</td>\n",
       "      <td>0.091491</td>\n",
       "      <td>0.134004</td>\n",
       "      <td>0.265232</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 34 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "  record type  0_pre-RR  0_post-RR   0_pPeak   0_tPeak   0_rPeak   0_sPeak  \\\n",
       "0    I01    N       163        165  0.069610 -0.083281  0.614133 -0.392761   \n",
       "1    I01    N       165        166 -0.097030  0.597254 -0.078704 -0.078704   \n",
       "2    I01    N       166        102  0.109399  0.680528 -0.010649 -0.010649   \n",
       "3    I01  VEB       102        231  0.176376  0.256431 -0.101098 -0.707525   \n",
       "4    I01    N       231        165  0.585577  0.607461 -0.083499 -0.083499   \n",
       "\n",
       "    0_qPeak  0_qrs_interval  ...   1_qPeak  1_qrs_interval  1_pq_interval  \\\n",
       "0  0.047159              15  ... -0.023370              14              3   \n",
       "1 -0.137781               3  ...  0.081637              15              5   \n",
       "2 -0.720620               6  ... -0.148539              33             13   \n",
       "3 -0.101098               4  ...  0.046898              21              9   \n",
       "4 -0.167858               3  ... -0.112552              32              5   \n",
       "\n",
       "   1_qt_interval  1_st_interval  1_qrs_morph0  1_qrs_morph1  1_qrs_morph2  \\\n",
       "0             23              6     -0.023370     -0.011650      0.082608   \n",
       "1             27              7      0.081637      0.102992      0.191225   \n",
       "2             52              6     -0.148539     -0.060620      0.081080   \n",
       "3             34              4      0.046898      0.083728      0.279512   \n",
       "4             43              6     -0.112552      0.012989      0.091491   \n",
       "\n",
       "   1_qrs_morph3  1_qrs_morph4  \n",
       "0      0.101373     -0.183387  \n",
       "1      0.217544     -0.068248  \n",
       "2      0.204400      0.335172  \n",
       "3      0.526785      0.450969  \n",
       "4      0.134004      0.265232  \n",
       "\n",
       "[5 rows x 34 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_data(folder_path, folder_name):\n",
    "    \"\"\"\n",
    "    folder_path: string,\n",
    "                 path of which folder has been saved on project\n",
    "                 (folder_path = 'raw_data/')\n",
    "\n",
    "    folder_name: string,\n",
    "                 name of csv file inside of folder.\n",
    "\n",
    "           Method:\n",
    "               load_data('raw_data/Arythmia_monitor.csv') return (pandas.core.frame.DataFrame)\n",
    "    \"\"\"\n",
    "\n",
    "    return pd.read_csv(folder_path + folder_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def clean():\n",
    "    \"\"\"\n",
    "    Put descriptions please of what this function is doing\n",
    "    \"\"\"\n",
    "    data = load_data('../raw_data/','INCART 2-lead Arrhythmia Database.csv')\n",
    "    type_names = {\n",
    "        'N': 'Normal',\n",
    "        'SVEB': 'Supraventricular ectopic beat',\n",
    "        'VEB': 'Ventricular ectopic beat',\n",
    "        'F': 'Fusion beat',\n",
    "        'Q': 'Unknown beat'\n",
    "    }\n",
    "    data = data.drop(columns=['record'])\n",
    "    return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def preprocess():\n",
    "    \"\"\"\n",
    "    The preprocess of data before training\n",
    "    \"\"\"\n",
    "    data = clean()\n",
    "\n",
    "    X = data.drop('type', axis=1)\n",
    "    y = data['type']\n",
    "    type_mapping = {'N': 0, 'SVEB': 1, 'VEB': 2, 'F': 3, 'Q': 4}\n",
    "    y = y.map(type_mapping)\n",
    "    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)\n",
    "\n",
    "    # Scaling the data before training\n",
    "    scaler = MinMaxScaler()\n",
    "    X_train = scaler.fit_transform(X_train)\n",
    "    X_test = scaler.transform(X_test)\n",
    "\n",
    "    #Resampling and rebalance the data\n",
    "    smote = SMOTE(sampling_strategy='auto', random_state=42, k_neighbors=3)\n",
    "    X_train_resampled, y_train_resampled = smote.fit_resample(X_train, y_train)\n",
    "\n",
    "    #Slicing to get light training memory\n",
    "    subset_size = 10000\n",
    "    X_train_subsample = X_train_resampled[:subset_size]\n",
    "    y_train_subsample = y_train_resampled[:subset_size]\n",
    "\n",
    "    return X_train_subsample, y_train_subsample, X_test, y_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def initialize_model():\n",
    "    \"\"\"\n",
    "    Good practice for any further modification\n",
    "    \"\"\"\n",
    "    return RandomForestClassifier(random_state=101, n_estimators=50)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def main_stream():\n",
    "\n",
    "    X_train, y_train, X_test, y_test = preprocess()\n",
    "    model = initialize_model()\n",
    "    model.fit(X_train, y_train)\n",
    "    y_pred = model.predict(X_test)\n",
    "    #accuracy = accuracy_score(y_test, y_pred)\n",
    "    return y_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 2, 0, ..., 0, 2, 0])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "main_output = main_stream()\n",
    "main_output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Index(['0_preRR', '0_postRR', '0_pPeak', '0_tPeak', '0_rPeak', '0_sPeak',\\n       '0_qPeak', '0_qrs_interval', '0_pq_interval', '0_qt_interval',\\n       '0_st_interval', '0_qrs_morph0', '0_qrs_morph1', '0_qrs_morph2',\\n       '0_qrs_morph3', '0_qrs_morph4', '1_preRR', '1_postRR', '1_pPeak',\\n       '1_tPeak', '1_rPeak', '1_sPeak', '1_qPeak', '1_qrs_interval',\\n       '1_pq_interval', '1_qt_interval', '1_st_interval', '1_qrs_morph0',\\n       '1_qrs_morph1', '1_qrs_morph2', '1_qrs_morph3', '1_qrs_morph4'],\\n      dtype='object')\""
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cols = str(df.columns[2:])\n",
    "cleanX = cols.replace('-','')\n",
    "cleanX"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "record             object\n",
       "type               object\n",
       "0_pre-RR            int64\n",
       "0_post-RR           int64\n",
       "0_pPeak           float64\n",
       "0_tPeak           float64\n",
       "0_rPeak           float64\n",
       "0_sPeak           float64\n",
       "0_qPeak           float64\n",
       "0_qrs_interval      int64\n",
       "0_pq_interval       int64\n",
       "0_qt_interval       int64\n",
       "0_st_interval       int64\n",
       "0_qrs_morph0      float64\n",
       "0_qrs_morph1      float64\n",
       "0_qrs_morph2      float64\n",
       "0_qrs_morph3      float64\n",
       "0_qrs_morph4      float64\n",
       "1_pre-RR            int64\n",
       "1_post-RR           int64\n",
       "1_pPeak           float64\n",
       "1_tPeak           float64\n",
       "1_rPeak           float64\n",
       "1_sPeak           float64\n",
       "1_qPeak           float64\n",
       "1_qrs_interval      int64\n",
       "1_pq_interval       int64\n",
       "1_qt_interval       int64\n",
       "1_st_interval       int64\n",
       "1_qrs_morph0      float64\n",
       "1_qrs_morph1      float64\n",
       "1_qrs_morph2      float64\n",
       "1_qrs_morph3      float64\n",
       "1_qrs_morph4      float64\n",
       "dtype: object"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dtypes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'record': dtype('O'), 'type': dtype('O'), '0_pre-RR': dtype('int64'), '0_post-RR': dtype('int64'), '0_pPeak': dtype('float64'), '0_tPeak': dtype('float64'), '0_rPeak': dtype('float64'), '0_sPeak': dtype('float64'), '0_qPeak': dtype('float64'), '0_qrs_interval': dtype('int64'), '0_pq_interval': dtype('int64'), '0_qt_interval': dtype('int64'), '0_st_interval': dtype('int64'), '0_qrs_morph0': dtype('float64'), '0_qrs_morph1': dtype('float64'), '0_qrs_morph2': dtype('float64'), '0_qrs_morph3': dtype('float64'), '0_qrs_morph4': dtype('float64'), '1_pre-RR': dtype('int64'), '1_post-RR': dtype('int64'), '1_pPeak': dtype('float64'), '1_tPeak': dtype('float64'), '1_rPeak': dtype('float64'), '1_sPeak': dtype('float64'), '1_qPeak': dtype('float64'), '1_qrs_interval': dtype('int64'), '1_pq_interval': dtype('int64'), '1_qt_interval': dtype('int64'), '1_st_interval': dtype('int64'), '1_qrs_morph0': dtype('float64'), '1_qrs_morph1': dtype('float64'), '1_qrs_morph2': dtype('float64'), '1_qrs_morph3': dtype('float64'), '1_qrs_morph4': dtype('float64')}\n"
     ]
    }
   ],
   "source": [
    "print(df.dtypes.to_dict())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('O')"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# _0preRR = '0_pre-RR'\n",
    "# _0postRR = '0_post-RR'\n",
    "# _0pPeak = '0_pPeak'\n",
    "# _0tPeak = '0_tPeak'\n",
    "# _0rPeak = '0_rPeak'\n",
    "# _0sPeak = '0_sPeak'\n",
    "# _0qPeak = '0_qPeak'\n",
    "# _0qrsinterval = '0_qrs_interval'\n",
    "# _0pqinterval = '0_pq_interval'\n",
    "# _0qtinterval = '0_qt_interval'\n",
    "# _0stinterval = '0_st_interval'\n",
    "# _0qrsmorph0 = '0_qrs_morph0'\n",
    "# _0qrsmorph1 = '0_qrs_morph1'\n",
    "# _0qrsmorph2 = '0_qrs_morph2'\n",
    "# _0qrsmorph3 = '0_qrs_morph3'\n",
    "# _0qrsmorph4 = '0_qrs_morph4'\n",
    "# _1preRR = '1_pre-RR'\n",
    "# _1postRR = '1_post-RR'\n",
    "# _1pPeak = '1_pPeak'\n",
    "# _1tPeak = '1_tPeak'\n",
    "# _1rPeak = '1_rPeak'\n",
    "# _1sPeak = '1_sPeak'\n",
    "# _1qPeak ='1_qPeak'\n",
    "# _1qrsinterval = '1_qrs_interval'\n",
    "# _1pqinterval = '1_pq_interval'\n",
    "# _1qtinterval = '1_qt_interval'\n",
    "# _1stinterval = '1_st_interval'\n",
    "# _1qrsmorph0 = '1_qrs_morph0'\n",
    "# _1qrsmorph1 = '1_qrs_morph1'\n",
    "# _1qrsmorph2 = '1_qrs_morph2'\n",
    "# _1qrsmorph3 = '1_qrs_morph3'\n",
    "# _1qrsmorph4 = '1_qrs_morph4'\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "{'0_pre-RR': pd.dtype('int64'),\n",
    "#     '0_post-RR': pd.dtype('int64'),\n",
    "#     '0_pPeak': pd.dtype('float64'),\n",
    "#     '0_tPeak': pd.dtype('float64'),\n",
    "#     '0_rPeak': pd.dtype('float64'),\n",
    "#     '0_sPeak': pd.dtype('float64'),\n",
    "#     '0_qPeak': pd.dtype('float64'),\n",
    "#     '0_qrs_interval': pd.dtype('int64'),\n",
    "#     '0_pq_interval': pd.dtype('int64'),\n",
    "#     '0_qt_interval': pd.dtype('int64'),\n",
    "#     '0_st_interval': pd.dtype('int64'),\n",
    "#     '0_qrs_morph0': pd.dtype('float64'),\n",
    "#     '0_qrs_morph1': pd.dtype('float64'),\n",
    "#     '0_qrs_morph2': pd.dtype('float64'),\n",
    "#     '0_qrs_morph3': pd.dtype('float64'),\n",
    "#     '0_qrs_morph4': pd.dtype('float64'),\n",
    "#     '1_pre-RR': pd.dtype('int64'),\n",
    "#     '1_post-RR': pd.dtype('int64'),\n",
    "#     '1_pPeak': pd.dtype('float64'),\n",
    "#     '1_tPeak': pd.dtype('float64'),\n",
    "#     '1_rPeak': pd.dtype('float64'),\n",
    "#     '1_sPeak': pd.dtype('float64'),\n",
    "#     '1_qPeak': pd.dtype('float64'),\n",
    "#     '1_qrs_interval': pd.dtype('int64'),\n",
    "#     '1_pq_interval': pd.dtype('int64'),\n",
    "#     '1_qt_interval': pd.dtype('int64'),\n",
    "#     '1_st_interval': pd.dtype('int64'),\n",
    "#     '1_qrs_morph0': pd.dtype('float64'),\n",
    "#     '1_qrs_morph1': pd.dtype('float64'),\n",
    "#     '1_qrs_morph2': pd.dtype('float64'),\n",
    "#     '1_qrs_morph3': pd.dtype('float64'),\n",
    "#     '1_qrs_morph4': pd.dtype('float64')}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fastapi import FastAPI\n",
    "from fastapi.middleware.cors import CORSMiddleware\n",
    "import pickle\n",
    "\n",
    "# instantiate\n",
    "app = FastAPI()\n",
    "\n",
    "# filename variable in case our pickle file changes\n",
    "pkl_file = \"local_model\" # or whatever the pickle filename is\n",
    "\n",
    "# load model from pickle file\n",
    "# important to do it outside the model so that we don't have to wait for it to load\n",
    "with open(f'heartbd/models/{pkl_file}.pkl','rb') as file:\n",
    "    '''\n",
    "    the path specified is where the file is being loaded from ('rb' is 'read binary')\n",
    "    '''\n",
    "    app.state.model = pickle.load(file)\n",
    "\n",
    "# implementing FastApi middleware because it is the recommended best practice\n",
    "app.add_middleware(\n",
    "    CORSMiddleware,\n",
    "    allow_origins=[\"*\"],\n",
    "    allow_credentials=True,\n",
    "    allow_methods=[\"*\"],\n",
    "    allow_headers=[\"*\"]\n",
    ")\n",
    "\n",
    "# define the root directory of the API\n",
    "@app.get('/')\n",
    "def root():\n",
    "\treturn {'greeting': 'ground control to major tom...'}\n",
    "\n",
    "# define our prediction and call the class of InputFeatures\n",
    "@app.get('/predict')\n",
    "def predict(_0preRR: int,\n",
    "    _0postRR: int,\n",
    "    _0pPeak: float,\n",
    "    _0tPeak: float,\n",
    "    _0rPeak: float,\n",
    "    _0sPeak: float,\n",
    "    _0qPeak: float,\n",
    "    _0qrsinterval: int,\n",
    "    _0pqinterval: int,\n",
    "    _0qtinterval: int,\n",
    "    _0stinterval: int,\n",
    "    _0qrsmorph0: float,\n",
    "    _0qrsmorph1: float,\n",
    "    _0qrsmorph2: float,\n",
    "    _0qrsmorph3: float,\n",
    "    _0qrsmorph4: float,\n",
    "    _1preRR: int,\n",
    "    _1postRR: int,\n",
    "    _1pPeak: float,\n",
    "    _1tPeak: float,\n",
    "    _1rPeak: float,\n",
    "    _1sPeak: float,\n",
    "    _1qPeak: float,\n",
    "    _1qrsinterval: int,\n",
    "    _1pqinterval: int,\n",
    "    _1qtinterval: int,\n",
    "    _1stinterval: int,\n",
    "    _1qrsmorph0: float,\n",
    "    _1qrsmorph1: float,\n",
    "    _1qrsmorph2: float,\n",
    "    _1qrsmorph3: float,\n",
    "    _1qrsmorph4: float,\n",
    "):\n",
    "    '''\n",
    "    our predict function in the API\n",
    "    '''\n",
    "    model = app.state.model # call the model from the pickle\n",
    "    assert model is not None # assuming the model exists in the first place\n",
    "    prediction = model.predict(_0preRR,\n",
    "                        _0postRR,\n",
    "                        _0pPeak,\n",
    "                        _0tPeak,\n",
    "                        _0rPeak,\n",
    "                        _0sPeak,\n",
    "                        _0qPeak,\n",
    "                        _0qrsinterval,\n",
    "                        _0pqinterval,\n",
    "                        _0qtinterval,\n",
    "                        _0stinterval,\n",
    "                        _0qrsmorph0,\n",
    "                        _0qrsmorph1,\n",
    "                        _0qrsmorph2,\n",
    "                        _0qrsmorph3,\n",
    "                        _0qrsmorph4,\n",
    "                        _1preRR,\n",
    "                        _1postRR,\n",
    "                        _1pPeak,\n",
    "                        _1tPeak,\n",
    "                        _1rPeak,\n",
    "                        _1sPeak,\n",
    "                        _1qPeak,\n",
    "                        _1qrsinterval,\n",
    "                        _1pqinterval,\n",
    "                        _1qtinterval,\n",
    "                        _1stinterval,\n",
    "                        _1qrsmorph0,\n",
    "                        _1qrsmorph1,\n",
    "                        _1qrsmorph2,\n",
    "                        _1qrsmorph3,\n",
    "                        _1qrsmorph4,) # pass all features into the api, feature variables indexed through the front end\n",
    "    y_pred = float(prediction[0])\n",
    "    return {\"result\": y_pred} # return a dictionary formatted as {result: <float>}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "heart-beat-decoder",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
